#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include "leptjson.h"

static int main_ret = 0;
static int test_count = 0;
static int test_pass = 0;

typedef struct {
    const char* json;
}lept_context;


#define EXPECT(c, ch)\
      do {\
         assert(*c->json == (ch));\
          c->json++;\
       }while(0)

// 跳过空白字符
static void lept_parse_whitespace(lept_context* c) {
    const char *p = c->json;
    while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
        p++;
    c->json = p;
}

static int lept_parse_null(lept_context* c, lept_value* v) {
    EXPECT(c, 'n');
    if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l')
        return LEPT_PARSE_INVALID_VALUE;
        // 跳过null
    c->json += 3;
    // 设置类型
    v->type = LEPT_NULL;
    return LEPT_PARSE_OK;
}

static int lept_parse_false(lept_context* c,lept_value* v){
    EXPECT(c, 'f');
    if(c->json[0] != 'a' || c->json[1] != 'l' || c->json[2] != 's' || c->json[3] != 'e')
        return LEPT_PARSE_INVALID_VALUE;
    c->json += 4;
    v->type = LEPT_FALSE;
    return LEPT_PARSE_OK;
}

static int lept_parse_true(lept_context* c,lept_value* v){
    if(c->json[0] != 't' || c->json[1] != 'r' || c->json[2] != 'u' || c->json[3] != 'e')
        return LEPT_PARSE_INVALID_VALUE;
    c->json += 3;
    v->type = LEPT_FALSE;
    return LEPT_PARSE_OK;
}
// 这里规定的特殊数字格式： 
//  [.]
//  [+-]
//  [0-9]
//  [eE] [0-9 | [+-]]
static int lept_parse_number(lept_context* c,lept_value* v){
    int hasDot = 0;  // 用于标记是否已经出现过小数点
    int hasE = 0;    // 用于标记是否已经出现过 'e' 或 'E'
    int signCount = 0;  // 用于记录正负号的数量
    for (int i = 0; i < strlen(c->json); i++) {
        if (isdigit(c->json[i])) {
            continue;
        } else if (c->json[i] == '.' &&!hasDot) {
            hasDot = 1;
        } else if ((c->json[i] == 'e' || c->json[i] == 'E') &&!hasE) {
            hasE = 1;
            // 检查 'e' 或 'E' 后面是否紧跟正负号或数字
            if (i + 1 < strlen(c->json) &&!(isdigit(c->json[i + 1]) || (c->json[i + 1] == '+' || c->json[i + 1] == '-'))) {
                return LEPT_PARSE_INVALID_VALUE;
            }
        } else if ((c->json[i] == '+' || c->json[i] == '-') && (i == 0 || (c->json[i - 1] == 'e' || c->json[i - 1] == 'E'))) {
            signCount++;
            if (signCount > 2) {  // 最多只能有一个正负号在开头，一个在 'e' 或 'E' 后
                return LEPT_PARSE_INVALID_VALUE;
            }
        } else {
            return LEPT_PARSE_INVALID_VALUE;
        }
    }

    return LEPT_PARSE_OK;
}

static int  lept_parse_array(lept_context* c,lept_value* v){
     EXPECT(c, '[');
     lept_parse_whitespace(c);
        if(*c->json == ']'){
            c->json++;
            v->type = LEPT_ARRAY;
            return LEPT_PARSE_OK;
        }
        for(;;){
            lept_parse_whitespace(c);
            if(c->json[0] == ']'){
                c->json++;
                v->type = LEPT_ARRAY;
                return LEPT_PARSE_OK;
            }else if(c->json[0] == ','){
                c->json++;
            }else if(c->json[0] == '\0'){
                return LEPT_PARSE_INVALID_VALUE;
            }else{
                c->json++;
            }
        }
}

static int  lept_parse_object(lept_context* c,lept_value* v){
     EXPECT(c, '{');
     lept_parse_whitespace(c);
        if(*c->json == '}'){
            c->json++;
            v->type = LEPT_ARRAY;
            return LEPT_PARSE_OK;
        }
        for(;;){
            lept_parse_whitespace(c);
            if(c->json[0] == '}'){
                c->json++;
                v->type = LEPT_OBJECT;
                return LEPT_PARSE_OK;
            }else if(c->json[0] == ','){
                c->json++;
            }else if(c->json[0] == '\0'){
                return LEPT_PARSE_INVALID_VALUE;
            }else{
                c->json++;
            }
        }
}

static int lept_parse_value(lept_context* c, lept_value* v) {
    switch (*c->json) {
        case 'n':  return lept_parse_null(c, v);
        case 'f':  return lept_parse_false(c, v); 
        case 't':  return lept_parse_true(c, v);
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9': return lept_parse_number(c, v);
        case '+': return lept_parse_number(c, v);
        case '-': return lept_parse_number(c, v);
        case '[': return lept_parse_array(c, v);
        case '{': return lept_parse_object(c, v);
        case '\0': return LEPT_PARSE_EXPECT_VALUE;
        default:   return LEPT_PARSE_INVALID_VALUE;
    }
}

int lept_parse_null_choose(lept_value* v, const char* json) {
    lept_context c;
    assert(v != NULL);
    c.json = json;
    v->type = LEPT_NULL;
    lept_parse_whitespace(&c);
    return lept_parse_value(&c, v);
}

int lept_parse_false_choose(lept_value* v, const char* json) {
    lept_context c;
    assert(v != NULL);
    c.json = json;
    v->type = LEPT_FALSE;
    lept_parse_whitespace(&c);
    return lept_parse_value(&c, v);
}

int lept_parse_true_choose(lept_value* v, const char* json){
    lept_context c;
    assert(v != NULL);
    c.json = json;
    v->type = LEPT_TRUE;
    lept_parse_whitespace(&c);
    return lept_parse_value(&c, v);
}

int lept_parse_number_choose(lept_value* v, const char* json){
    lept_context c;
    assert(v != NULL);
    c.json = json;
    v->type = LEPT_NUMBER;
    lept_parse_whitespace(&c);
    return lept_parse_value(&c, v);
}

int lept_parse_array_choose(lept_value* v, const char* json){
    lept_context c;
    assert(v != NULL);
    c.json = json;
    v->type = LEPT_ARRAY;
    lept_parse_whitespace(&c);
    return lept_parse_value(&c, v);
}

int lept_parse_object_choose(lept_value* v, const char* json){
    lept_context c;
    assert(v != NULL);
    c.json = json;
    v->type = LEPT_OBJECT;
    lept_parse_whitespace(&c);
    return lept_parse_value(&c, v);
}

lept_type lept_get_type(const lept_value* v) {
    assert(v != NULL);
    return v->type;
}


// 判断结果，期待值，实际值，格式化输出
#define EXPECT_EQ_BASE(equality, expect, actual, format)                                                           \
    do                                                                                                             \
    {                                                                                                              \
        test_count++;                                                                                              \
        if (equality)                                                                                              \
            test_pass++;                                                                                           \
        else                                                                                                       \
        {                                                                                                          \
            fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual); \
            main_ret = 1;                                                                                          \
        }                                                                                                          \
    } while (0)
// 判断expect与actual是否相等，相等则通过 main_ret = 0
#define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d")

static void test_parse_null()
{
    lept_value v;
    v.type = LEPT_FALSE;
    EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse_null_choose(&v, "null"));
}

static void test_parse_false()
{
    lept_value v;
    v.type = LEPT_FALSE;
    EXPECT_EQ_INT(LEPT_PARSE_OK,lept_parse_false_choose(&v, "false"));
}

static void test_parse_true()
{
    lept_value v;
    v.type = LEPT_FALSE;
    EXPECT_EQ_INT(LEPT_PARSE_OK,lept_parse_true_choose(&v, "false"));
}

static void test_parse_number()
{
    lept_value v;
    v.type = LEPT_FALSE;
    EXPECT_EQ_INT(LEPT_PARSE_OK,lept_parse_number_choose(&v, "-3.67"));
}

static void test_parse_array()
{
    lept_value v;
    v.type = LEPT_FALSE;
    EXPECT_EQ_INT(LEPT_PARSE_OK,lept_parse_array_choose(&v, "[1,3,5]"));
}

static void test_parse_object()
{
    lept_value v;
    v.type = LEPT_FALSE;
    EXPECT_EQ_INT(LEPT_PARSE_OK,lept_parse_object_choose(&v, "{1,3,5}"));
}

static void test_parse() {
    test_parse_null();
    test_parse_false();
    test_parse_true();
    test_parse_number();
    test_parse_array();
    test_parse_object();
    
}

int main() {
    test_parse();
    printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count);
    return main_ret;
}